<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="prism-import.html">

<!--
Syntax highlighting via [Prism](http://prismjs.com/).

Place a `<prism-highlighter>` in your document, preferably as a direct child of
`<body>`. It will listen for `syntax-highlight` events on its parent element,
and annotate the code being provided via that event.

The `syntax-highlight` event's detail is expected to have a `code` property
containing the source to highlight. The event detail can optionally contain a
`lang` property, containing a string like `"html"`, `"js"`, etc.

This flow is supported by [`<marked-element>`](https://github.com/PolymerElements/marked-element).

@element prism-highlighter
@demo demo/index.html
-->
<script>
(function() {

  'use strict';

  var HIGHLIGHT_EVENT = 'syntax-highlight';

  Polymer({

    is: 'prism-highlighter',
    
    properties: {
      /**
       * Adds languages outside of the core Prism languages.
       *
       * Prism includes a few languages in the core library:
       *   - JavaScript
       *   - Markup
       *   - CSS
       *   - C-Like
       * Use this property to extend the core set with other Prism
       * components and custom languages.
       *
       * Example:
       *   ```
       *   <!-- with languages = {'custom': myCustomPrismLang}; -->
       *   <!-- or languages = Prism.languages; -->
       *   <prism-highlighter languages="[[languages]]"></prism-highlighter>
       *   ```
       *
       * @attribute languages
       * @type {!Object}
       */
      languages: {
        type: Object,
        value: function() {
          return {};
        }
      }
    },

    ready: function() {
      this._handler = this._highlight.bind(this);
    },

    attached: function() {
      (this.parentElement || this.parentNode.host).addEventListener(HIGHLIGHT_EVENT, this._handler);
    },

    detached: function() {
      (this.parentElement || this.parentNode.host).removeEventListener(HIGHLIGHT_EVENT, this._handler);
    },

    /**
     * Handle the highlighting event, if we can.
     *
     * @param {!CustomEvent} event
     */
    _highlight: function(event) {
      if (!event.detail || !event.detail.code) {
        Polymer.Base._warn('Malformed', HIGHLIGHT_EVENT, 'event:', event.detail);
        return;
      }

      event.stopPropagation();

      var detail = event.detail;
      detail.code = Prism.highlight(detail.code, this._detectLang(detail.code, detail.lang));
    },

    /**
     * Picks a Prism formatter based on the `lang` hint and `code`.
     *
     * @param {string} code The source being highlighted.
     * @param {string=} lang A language hint (e.g. ````LANG`).
     * @return {!prism.Lang}
     */
    _detectLang: function(code, lang) {
      if (!lang) {
        // Stupid simple detection if we have no lang, courtesy of:
        // https://github.com/robdodson/mark-down/blob/ac2eaa/mark-down.html#L93-101
        return code.match(/^\s*</) ? Prism.languages.markup : Prism.languages.javascript;
      }

      if (this.languages[lang]) {
        return this.languages[lang];
      } else if (Prism.languages[lang]) {
        return Prism.languages[lang];
      }
      switch (lang.substr(0, 2)) {
        case 'js':
        case 'es':
          return Prism.languages.javascript;
        case 'c':
          return Prism.languages.clike;
        default:
          // The assumption is that you're mostly documenting HTML when in HTML.
          return Prism.languages.markup;
      }
    },

  });

})();
</script>
